1
|
|
|
/** global: UB */ |
2
|
|
|
|
3
|
|
|
UB.intMaxValue = 2147483647; |
4
|
|
|
UB.intMinValue = -2147483648; |
5
|
|
|
UB.floatMaxValue = 3.40282e+038; /// 038 or 056? .. it was originally 038F |
6
|
|
|
UB.floatMinValue = -3.40282e+038; |
7
|
|
|
UB.doubleMaxValue = 9223372036854775807; |
8
|
|
|
UB.doubleMinValue = -9223372036854775808; |
9
|
|
|
|
10
|
|
|
UB.roman1s = ["", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"]; |
11
|
|
|
UB.roman10s = ["", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"]; |
12
|
|
|
UB.roman100s = ["", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"]; |
13
|
|
|
UB.roman1000s = ["", "m", "mm", "mmm", "mmmm", "", "", "", "", ""]; |
14
|
|
|
UB.roman = [UB.roman1s, UB.roman10s, UB.roman100s, UB.roman1000s]; |
15
|
|
|
|
16
|
|
|
UB.letterLegal = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH", "II", "JJ", "KK", "LL", "MM", "NN", "OO", "PP", "QQ", "RR", "SS", "TT", "UU", "VV", "WW", "XX", "YY", "ZZ", "AAA", "BBB", "CCC", "DDD", "EEE", "FFF", "GGG", "HHH", "III", "JJJ", "KKK", "LLL", "MMM", "NNN", "OOO", "PPP", "QQQ", "RRR", "SSS", "TTT", "UUU", "VVV", "WWW", "XXX", "YYY", "ZZZ", "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLL", "MMMM", "NNNN", "OOOO", "PPPP", "QQQQ", "RRRR", "SSSS", "TTTT", "UUUU", "VVVV", "WWWW", "XXXX", "YYYY", "ZZZZ", "AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEE", "FFFFF", "GGGGG", "HHHHH", "IIIII", "JJJJJ", "KKKKK", "LLLLL", "MMMMM", "NNNNN", "OOOOO", "PPPPP", "QQQQQ", "RRRRR", "SSSSS", "TTTTT", "UUUUU", "VVVVV", "WWWWW", "XXXXX", "YYYYY", "ZZZZZ"]; |
17
|
|
|
UB.letterExcel = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BK", "BL", "BM", "BN", "BO", "BP", "BQ", "BR", "BS", "BT", "BU", "BV", "BW", "BX", "BY", "BZ", "CA", "CB", "CC", "CD", "CE", "CF", "CG", "CH", "CI", "CJ", "CK", "CL", "CM", "CN", "CO", "CP", "CQ", "CR", "CS", "CT", "CU", "CV", "CW", "CX", "CY", "CZ", "DA", "DB", "DC", "DD", "DE", "DF", "DG", "DH", "DI", "DJ", "DK", "DL", "DM", "DN", "DO", "DP", "DQ", "DR", "DS", "DT", "DU", "DV", "DW", "DX", "DY", "DZ"]; |
18
|
|
|
|
19
|
|
|
UB.decZeros = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; |
20
|
|
|
UB.hexChars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"]; |
21
|
|
|
UB.toDegrees = (180 / Math.PI); |
22
|
|
|
UB.toRadians = (Math.PI / 180); |
23
|
|
|
|
24
|
|
|
UB.minOf3 = function(num1, num2, num3){ |
25
|
|
|
if (num1 < num2) { |
26
|
|
|
if (num1 < num3) { |
27
|
|
|
return num1; |
28
|
|
|
} |
29
|
|
|
return num3; |
30
|
|
|
} |
31
|
|
|
if (num2 < num3) { |
32
|
|
|
return num2; |
33
|
|
|
} |
34
|
|
|
return num3; |
35
|
|
|
}; |
36
|
|
|
UB.maxOf3 = function(num1, num2, num3){ |
37
|
|
|
if (num1 > num2) { |
38
|
|
|
if (num1 > num3) { |
39
|
|
|
return num1; |
40
|
|
|
} |
41
|
|
|
return num3; |
42
|
|
|
} |
43
|
|
|
if (num2 > num3) { |
44
|
|
|
return num2; |
45
|
|
|
} |
46
|
|
|
return num3; |
47
|
|
|
}; |
48
|
|
|
|
49
|
|
|
UB.minOf4 = function(num1, num2, num3, num4){ |
50
|
|
|
if (num1 < num2) { |
51
|
|
|
|
52
|
|
|
// 1, 3, 4 |
53
|
|
|
if (num1 < num3) { |
54
|
|
|
|
55
|
|
|
// 1, 4 |
56
|
|
|
if (num1 < num4) { |
57
|
|
|
return num1; |
58
|
|
|
} |
59
|
|
|
return num4; |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
// 3, 4 |
63
|
|
|
if (num3 < num4) { |
64
|
|
|
return num3; |
65
|
|
|
} |
66
|
|
|
return num4; |
67
|
|
|
|
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
// 2, 3, 4 |
71
|
|
|
if (num2 < num3) { |
72
|
|
|
|
73
|
|
|
// 2, 4 |
74
|
|
|
if (num2 < num4) { |
75
|
|
|
return num2; |
76
|
|
|
} |
77
|
|
|
return num4; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
// 3, 4 |
81
|
|
|
if (num3 < num4) { |
82
|
|
|
return num3; |
83
|
|
|
} |
84
|
|
|
return num4; |
85
|
|
|
}; |
86
|
|
|
UB.maxOf4 = function(num1, num2, num3, num4){ |
87
|
|
|
if (num1 > num2) { |
88
|
|
|
|
89
|
|
|
// 1, 3, 4 |
90
|
|
|
if (num1 > num3) { |
91
|
|
|
|
92
|
|
|
// 1, 4 |
93
|
|
|
if (num1 > num4) { |
94
|
|
|
return num1; |
95
|
|
|
} |
96
|
|
|
return num4; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
// 3, 4 |
100
|
|
|
if (num3 > num4) { |
101
|
|
|
return num3; |
102
|
|
|
} |
103
|
|
|
return num4; |
104
|
|
|
|
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
// 2, 3, 4 |
108
|
|
|
if (num2 > num3) { |
109
|
|
|
|
110
|
|
|
// 2, 4 |
111
|
|
|
if (num2 > num4) { |
112
|
|
|
return num2; |
113
|
|
|
} |
114
|
|
|
return num4; |
115
|
|
|
|
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
// 3, 4 |
119
|
|
|
if (num3 > num4) { |
120
|
|
|
return num3; |
121
|
|
|
} |
122
|
|
|
return num4; |
123
|
|
|
}; |
124
|
|
|
|
125
|
|
|
/** calc overlap of 2 numeric ranges */ |
126
|
|
|
UB.overlap = function(value1Start, value1End, value2Start, value2End){ |
127
|
|
|
|
128
|
|
|
// swap if reversed |
129
|
|
|
if (value1Start > value1End) { |
130
|
|
|
var temp = value1Start; |
131
|
|
|
value1Start = value1End; |
132
|
|
|
value1End = temp; |
133
|
|
|
} |
134
|
|
|
if (value2Start > value2End) { |
135
|
|
|
temp = value2Start; |
136
|
|
|
value2Start = value2End; |
137
|
|
|
value2End = temp; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
// exit if no overlap |
141
|
|
|
if (value1End < value2Start || value2End < value1Start) { |
142
|
|
|
return 0; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
// return overlap of 2 ranges |
146
|
|
|
if (value1Start >= value2Start && value1End <= value2End) { |
147
|
|
|
return (value1End - value1Start); |
148
|
|
|
} else if (value2Start >= value1Start && value2End <= value1End) { |
149
|
|
|
return (value2End - value2Start); |
150
|
|
|
} else if (value1Start < value2Start && value1End <= value2End) { |
151
|
|
|
return (value1End - value2Start); |
152
|
|
|
} else if (value2Start < value1Start && value2End <= value1End) { |
153
|
|
|
return (value2End - value1Start); |
154
|
|
|
} |
155
|
|
|
return 0; |
156
|
|
|
}; |
157
|
|
|
|
158
|
|
|
// distance between 2 lat/lon coords |
159
|
|
|
UB.latLonDistance = function(latitude1, longitude1, latitude2, longitude2){ |
160
|
|
|
|
161
|
|
|
// all lat/lons are floating point numbers in degrees |
162
|
|
|
|
163
|
|
|
var theta = longitude1 - longitude2; |
164
|
|
|
var miles = (Math.sin(latitude1*UB.toRadians)*Math.sin(latitude2*UB.toRadians)) + (Math.cos(latitude1*UB.toRadians)*Math.cos(latitude2*UB.toRadians)*Math.cos(theta*UB.toRadians)); |
165
|
|
|
miles = Math.acos(miles); |
166
|
|
|
miles = (miles * UB.toDegrees); |
167
|
|
|
|
168
|
|
|
miles = miles * 60 * 1.1515; |
169
|
|
|
var feet = miles*5280; |
170
|
|
|
var yards = feet / 3; |
171
|
|
|
var kilometers = miles*1.609344; |
172
|
|
|
var meters = kilometers*1000; |
173
|
|
|
return [miles, feet, yards, kilometers, meters]; |
174
|
|
|
}; |
175
|
|
|
|
176
|
|
|
|
177
|
|
|
var stringFuncs = { |
178
|
|
|
|
179
|
|
|
/** CONVERT LEGAL LETTER TO NUMBER .. A = 1, B = 2, C = 3 */ |
180
|
|
|
legalNumeralToNumber: function(zeroBased){ |
181
|
|
|
var s = this.toString(); |
182
|
|
|
return UB.letterLegal.indexOf(s.toUpperCase()) + (zeroBased ? 0 : 1); |
183
|
|
|
}, |
184
|
|
|
/** CONVERT EXCEL COLUMN ID TO NUMBER .. A = 1, B = 2, C = 3 */ |
185
|
|
|
excelColumnToNumber: function(zeroBased = false){ |
186
|
|
|
var s = this.toString(); |
187
|
|
|
return UB.letterExcel.indexOf(s.toUpperCase()) + (zeroBased ? 0 : 1); |
188
|
|
|
}, |
189
|
|
|
|
190
|
|
|
hexToDecimal: function(onlyDigits = 0){ |
191
|
|
|
var hex = this.toString(); |
192
|
|
|
hex = hex.toUpperCase(); |
193
|
|
|
|
194
|
|
|
// remove prefix |
195
|
|
|
if (hex.indexOf("0X") === 0){ |
196
|
|
|
hex = hex.substr(2); |
197
|
|
|
}else if (hex.charAt(0) == "#"){ |
198
|
|
|
hex = hex.substr(1); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
if (onlyDigits) { |
202
|
|
|
hex = hex.substr(0, onlyDigits); |
203
|
|
|
} |
204
|
|
|
return int("0x" + hex); |
205
|
|
|
}, |
206
|
|
|
|
207
|
|
|
binaryToDecimal: function(){ |
208
|
|
|
var bin = this.toString(); |
209
|
|
|
bin = bin.toUpperCase(); |
210
|
|
|
|
211
|
|
|
// remove prefix |
212
|
|
|
if (bin.indexOf("0B") === 0){ |
213
|
|
|
bin = bin.substr(2); |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
var byte = 0; |
217
|
|
|
for (var i = 0, il = bin.length, il2 = bin.length - 1;i<il;i++){ |
218
|
|
|
byte += uint(bin.charAt(il2 - i)) * Math.pow(2,i); |
219
|
|
|
} |
220
|
|
|
return byte; |
221
|
|
|
}, |
222
|
|
|
|
223
|
|
|
none:null |
224
|
|
|
}; |
225
|
|
|
|
226
|
|
|
// register funcs |
227
|
|
|
UB.registerFuncs(String.prototype, stringFuncs); |
228
|
|
|
|
229
|
|
|
|
230
|
|
|
|
231
|
|
|
var numberFuncs = { |
232
|
|
|
|
233
|
|
View Code Duplication |
distance: function(v2, type){ |
|
|
|
|
234
|
|
|
var v1 = this; |
235
|
|
|
// type .. 0=any, 1=pos, 2=neg |
236
|
|
|
var v = v2 - v1; |
237
|
|
|
if (type == 1) { |
238
|
|
|
return v > 0 ? v : -v; |
239
|
|
|
}else if (type == 2) { |
240
|
|
|
return v > 0 ? -v : v; |
241
|
|
|
} |
242
|
|
|
return v; |
243
|
|
|
}, |
244
|
|
|
round: function(){ |
245
|
|
|
return Math.round(this); |
246
|
|
|
}, |
247
|
|
|
ceil: function(){ |
248
|
|
|
return Math.ceil(this); |
249
|
|
|
}, |
250
|
|
|
floor: function(){ |
251
|
|
|
return Math.floor(this); |
252
|
|
|
}, |
253
|
|
|
abs: function(negative = false){ |
254
|
|
|
var v = this; |
255
|
|
|
if (negative){ |
256
|
|
|
return v > 0 ? -v : v; |
257
|
|
|
} |
258
|
|
|
return v > 0 ? v : -v; |
259
|
|
|
}, |
260
|
|
|
acos: function(degrees = false){ |
261
|
|
|
var v = this; |
262
|
|
|
if (degrees) { |
263
|
|
|
return Math.acos(v) * UB.toDegrees; |
264
|
|
|
} |
265
|
|
|
return Math.acos(v); |
266
|
|
|
}, |
267
|
|
|
asin: function(degrees = false){ |
268
|
|
|
var v = this; |
269
|
|
|
if (degrees) { |
270
|
|
|
return Math.asin(v) * UB.toDegrees; |
271
|
|
|
} |
272
|
|
|
return Math.asin(v); |
273
|
|
|
}, |
274
|
|
|
atan: function(degrees = false){ |
275
|
|
|
var v = this; |
276
|
|
|
if (degrees) { |
277
|
|
|
return Math.atan(v) * UB.toDegrees; |
278
|
|
|
} |
279
|
|
|
return Math.atan(v); |
280
|
|
|
}, |
281
|
|
|
atan2: function(x, degrees = false){ |
282
|
|
|
var y = this; |
283
|
|
|
if (degrees) { |
284
|
|
|
return Math.atan2(y, x) * UB.toDegrees; |
285
|
|
|
} |
286
|
|
|
return Math.atan2(y, x); |
287
|
|
|
}, |
288
|
|
|
exp: function(){ |
289
|
|
|
var v = this; |
290
|
|
|
return Math.exp(v); |
291
|
|
|
}, |
292
|
|
|
log: function(){ |
293
|
|
|
var v = this; |
294
|
|
|
return Math.log(v); |
295
|
|
|
}, |
296
|
|
|
pow: function(power){ |
297
|
|
|
var base = this; |
298
|
|
|
return Math.pow(base, power) |
299
|
|
|
}, |
300
|
|
|
sin: function(degrees = false){ |
301
|
|
|
var angle = this; |
302
|
|
|
if (degrees) { |
303
|
|
|
return Math.sin(angle * UB.toRadians); |
304
|
|
|
} |
305
|
|
|
return Math.sin(angle); |
306
|
|
|
}, |
307
|
|
|
cos: function(degrees = false){ |
308
|
|
|
var angle = this; |
309
|
|
|
if (degrees) { |
310
|
|
|
return Math.cos(angle * UB.toRadians); |
311
|
|
|
} |
312
|
|
|
return Math.cos(angle); |
313
|
|
|
}, |
314
|
|
|
tan: function(degrees = false){ |
315
|
|
|
var angle = this; |
316
|
|
|
if (degrees) { |
317
|
|
|
return Math.tan(angle * UB.toRadians); |
318
|
|
|
} |
319
|
|
|
return Math.tan(angle); |
320
|
|
|
}, |
321
|
|
|
sqrt: function(){ |
322
|
|
|
var v = this; |
323
|
|
|
return Math.sqrt(v); |
324
|
|
|
}, |
325
|
|
|
compare: function(v2){ |
326
|
|
|
var v1 = this; |
327
|
|
|
if (v1 < v2) { |
328
|
|
|
return -1; |
329
|
|
|
} |
330
|
|
|
if (v1 > v2) { |
331
|
|
|
return 1; |
332
|
|
|
} |
333
|
|
|
return 0; |
334
|
|
|
}, |
335
|
|
|
positive: function(){ |
336
|
|
|
var val = this; |
337
|
|
|
return val > 0 ? val : -val; |
338
|
|
|
}, |
339
|
|
|
negative: function(){ |
340
|
|
|
var val = this; |
341
|
|
|
return val > 0 ? -val : val; |
342
|
|
|
}, |
343
|
|
|
|
344
|
|
|
exists: function(zeroOK = false){ |
345
|
|
|
var v = this; |
346
|
|
|
if (zeroOK) { |
347
|
|
|
return (v == v); |
348
|
|
|
} |
349
|
|
|
return v == v && v != 0; |
350
|
|
|
}, |
351
|
|
|
|
352
|
|
|
|
353
|
|
|
min: function(num2){ |
354
|
|
|
var num1 = this; |
355
|
|
|
if (num1 < num2) { |
356
|
|
|
return num1; |
357
|
|
|
} |
358
|
|
|
return num2; |
359
|
|
|
}, |
360
|
|
|
max: function(num2){ |
361
|
|
|
var num1 = this; |
362
|
|
|
if (num1 > num2) { |
363
|
|
|
return num1; |
364
|
|
|
} |
365
|
|
|
return num2; |
366
|
|
|
}, |
367
|
|
|
atMost: function(limit){ |
368
|
|
|
var num = this; |
369
|
|
|
return num > limit ? limit : num; |
370
|
|
|
}, |
371
|
|
|
atLeast: function(limit){ |
372
|
|
|
var num = this; |
373
|
|
|
return num < limit ? limit : num; |
374
|
|
|
}, |
375
|
|
|
|
376
|
|
|
|
377
|
|
|
|
378
|
|
|
/** Render a percentage (25%) using 2 values */ |
379
|
|
|
percentageToString: function(current, decimals = 0){ |
380
|
|
|
var total = this; |
381
|
|
|
return ((current / total) * 100).roundTo(decimals) + "%"; |
382
|
|
|
}, |
383
|
|
|
|
384
|
|
|
|
385
|
|
|
// CONVERT TO ABBREVIATION .. 1.5K |
386
|
|
|
toAbbreviation: function(decimals = 1){ |
387
|
|
|
var num = this; |
388
|
|
|
if (num < 0) { |
389
|
|
|
return "-" + (-num).toAbbreviation; // -5.2K, -5.2M .. |
390
|
|
|
} |
391
|
|
|
if (num < 1000) { |
392
|
|
|
return String(num); // 520 |
393
|
|
|
} |
394
|
|
|
if (num < 1000000) { |
395
|
|
|
return (num / 1000).roundToDigits(decimals) + 'K'; // 5.2K |
396
|
|
|
} |
397
|
|
|
if (num < 1000000000) { |
398
|
|
|
return (num / 1000000).roundToDigits(decimals) + 'M'; // 5.2M |
399
|
|
|
} |
400
|
|
|
return (num / 1000000000).roundToDigits(decimals) + 'G'; // 5.2B |
401
|
|
|
}, |
402
|
|
|
|
403
|
|
|
|
404
|
|
|
// CONVERT TO ROMAN |
405
|
|
|
toRomanNumeral: function(){ |
406
|
|
|
var n = this; |
407
|
|
|
if (n < 1) { |
408
|
|
|
n = 1; |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
// exit quickly if single digit |
412
|
|
|
if (n <= 9) { |
413
|
|
|
return UB.roman1s[n]; |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
// create roman number if longer |
417
|
|
|
var str = n.toString(); |
418
|
|
|
var output = []; |
419
|
|
|
for (var n = 0, nl = str.length;n<nl;n++){ |
|
|
|
|
420
|
|
|
var series = ((nl - 1) - n); |
421
|
|
|
var charIndex = int(str.charAt(n)); |
422
|
|
|
output.push(UB.roman[series][charIndex]); |
423
|
|
|
} |
424
|
|
|
return output.join(""); |
425
|
|
|
}, |
426
|
|
|
|
427
|
|
|
/** CONVERT TO LEGAL LETTER .. 1 = A, 2 = B, 3 = C .. AA, BB, CC */ |
428
|
|
|
toLegalNumeral: function(){ |
429
|
|
|
var n = this; |
430
|
|
|
if (n < 1) { |
431
|
|
|
n = 1; |
432
|
|
|
} |
433
|
|
|
return UB.letterLegal[n]; |
434
|
|
|
}, |
435
|
|
|
// CONVERT TO NORMAL LETTER .. A, B, C .. AB, AB, AC .. BA, BB, BC |
436
|
|
|
toLetterNumeral: function(){ |
437
|
|
|
var n = this; |
438
|
|
|
if (n <= 26) { |
439
|
|
|
return UB.letterLegal[n]; |
440
|
|
|
} |
441
|
|
|
return "?"; |
442
|
|
|
}, |
443
|
|
|
/** CONVERT TO EXCEL COLUMN ID .. 1 = A, 2 = B, 3 = C .. AA, AB, AC */ |
444
|
|
|
toExcelColumn: function(zeroBased = false){ |
445
|
|
|
var n = this; |
446
|
|
|
var min = zeroBased?0:1; |
447
|
|
|
if (n < min) { |
448
|
|
|
n = min; |
449
|
|
|
} |
450
|
|
|
return UB.letterExcel[zeroBased ? n : n-1]; |
451
|
|
|
}, |
452
|
|
|
|
453
|
|
|
// CONVERT TO ORDINAL FORMAT .. 1st, 2nd, 3rd |
454
|
|
|
toOrdinal: function(){ |
455
|
|
|
var i = this; |
456
|
|
|
var j = i % 10; |
457
|
|
|
var k = i % 100; |
458
|
|
|
if (j == 1 && k != 11) { |
459
|
|
|
return i + "st"; |
460
|
|
|
} |
461
|
|
|
if (j == 2 && k != 12) { |
462
|
|
|
return i + "nd"; |
463
|
|
|
} |
464
|
|
|
if (j == 3 && k != 13) { |
465
|
|
|
return i + "rd"; |
466
|
|
|
} |
467
|
|
|
return i + "th"; |
468
|
|
|
}, |
469
|
|
|
|
470
|
|
|
|
471
|
|
|
// OR |
472
|
|
|
or: function(returnVal, ifNull = 0){ |
473
|
|
|
var n = this; |
474
|
|
|
if (n == ifNull) { |
475
|
|
|
return returnVal; |
476
|
|
|
} |
477
|
|
|
return n; |
478
|
|
|
}, |
479
|
|
|
|
480
|
|
|
|
481
|
|
|
/** Calc padding for a given length */ |
482
|
|
|
padding: function(multipleOf){ |
483
|
|
|
var length = this; |
484
|
|
|
return (multipleOf - (length % multipleOf)); |
485
|
|
|
}, |
486
|
|
|
|
487
|
|
|
multipleOf: function(multipleOf){ |
488
|
|
|
var value = this; |
489
|
|
|
return value + (multipleOf - (value % multipleOf)); |
490
|
|
|
}, |
491
|
|
|
|
492
|
|
|
/** Calc x % of the given value */ |
493
|
|
|
percentage: function(percentWanted){ |
494
|
|
|
var val100Percent = this; |
495
|
|
|
if (percentWanted == 100) { |
496
|
|
|
return val100Percent; |
497
|
|
|
} |
498
|
|
|
return val100Percent * (percentWanted / 100.0); |
499
|
|
|
}, |
500
|
|
|
|
501
|
|
|
/** Calc the % of otherVal in relation to val100Percent */ |
502
|
|
|
percentOf: function(otherVal){ |
503
|
|
|
var val100Percent = this; |
504
|
|
|
return (otherVal / val100Percent) * 100.0; |
505
|
|
|
}, |
506
|
|
|
|
507
|
|
|
/** Calc the difference between 2 numbers in % |
508
|
|
|
// ... 100, 50 shows -50% difference |
509
|
|
|
// ... 100, 150 shows 50% difference */ |
510
|
|
|
percentDifference: function(otherVal){ |
511
|
|
|
var val100Percent = this; |
512
|
|
|
return ((otherVal - val100Percent) / val100Percent) * 100.0; |
513
|
|
|
}, |
514
|
|
|
|
515
|
|
|
/** Returns the number halfway between the 2 given numbers |
516
|
|
|
Value1 can be greater than Value2. */ |
517
|
|
|
between: function(value2){ |
518
|
|
|
return this.middle(value2); |
519
|
|
|
}, |
520
|
|
|
|
521
|
|
|
/** Returns the number halfway between the 2 given numbers |
522
|
|
|
Value1 can be greater than Value2. */ |
523
|
|
|
middle: function(value2){ |
524
|
|
|
var value1 = this; |
525
|
|
|
if (value1 > value2) { |
526
|
|
|
return value2 + ((value1 - value2) / 2); |
527
|
|
|
} |
528
|
|
|
return value1 + ((value2 - value1) / 2); |
529
|
|
|
}, |
530
|
|
|
|
531
|
|
|
calcScale: function(targetValue){ |
532
|
|
|
var value = this; |
533
|
|
|
if (targetValue === 0 && value === 0) { |
534
|
|
|
return 0; |
535
|
|
|
} |
536
|
|
|
return (value / targetValue); |
537
|
|
|
}, |
538
|
|
|
|
539
|
|
|
ensure: function(defaultVal){ |
540
|
|
|
var value = this; |
541
|
|
|
if (value === 0) { |
542
|
|
|
return defaultVal; |
543
|
|
|
} |
544
|
|
|
return value; |
545
|
|
|
}, |
546
|
|
|
|
547
|
|
|
snapToHigher: function(snapBy){ |
548
|
|
|
var val = this; |
549
|
|
|
return Math.ceil(val / snapBy) * snapBy; |
550
|
|
|
}, |
551
|
|
|
snapToLower: function(snapBy){ |
552
|
|
|
var val = this; |
553
|
|
|
return Math.floor(val / snapBy) * snapBy; |
554
|
|
|
}, |
555
|
|
|
snapTo: function(snapBy){ |
556
|
|
|
var val = this; |
557
|
|
|
return Math.round(val / snapBy) * snapBy; |
558
|
|
|
}, |
559
|
|
|
|
560
|
|
|
toInt: function(round){ |
561
|
|
|
var num = this; |
562
|
|
|
if (!round || round == "truncate") { |
563
|
|
|
return parseInt(num); |
564
|
|
|
} |
565
|
|
|
if (round == "round") { |
566
|
|
|
return Math.round(num); |
567
|
|
|
} |
568
|
|
|
if (round == "floor") { |
569
|
|
|
return Math.floor(num); |
570
|
|
|
} |
571
|
|
|
if (round == "ceiling") { |
572
|
|
|
return Math.ceil(num); |
573
|
|
|
} |
574
|
|
|
return 0; |
575
|
|
|
}, |
576
|
|
|
|
577
|
|
|
/** |
578
|
|
|
* Formats a Number adding commas and the specified decimal digits. |
579
|
|
|
* Supports the million/billion and lakh/crore system. |
580
|
|
|
* |
581
|
|
|
* @param system "million" or "lakh" |
582
|
|
|
* @param decimals -1 = keep exact decimals as number, 0 = no decimals, 1+ = specific decimals |
583
|
|
|
* @param alwaysShowDecimal add decimal even if decimal part is 0 |
584
|
|
|
*/ |
585
|
|
|
formatNumber: function(system, decimals = -1, alwaysShowDecimal = false){ |
586
|
|
|
var num = this; |
587
|
|
|
|
588
|
|
|
var commas = system == "lakh" ? 2 : 3; |
589
|
|
|
|
590
|
|
|
// test if number is negative |
591
|
|
|
var neg = false; |
592
|
|
|
if (num < 0) { |
593
|
|
|
neg = true; |
594
|
|
|
num = -num; |
595
|
|
|
} |
596
|
|
|
// get the left number |
597
|
|
|
var numStr = String(num); |
598
|
|
|
var hasDot = numStr.indexOf(".")>-1; |
599
|
|
|
if (hasDot) { |
600
|
|
|
var parts = numStr.split("."); |
601
|
|
|
var whole = parts[0]; |
602
|
|
|
var decimal = parts[1]; |
603
|
|
|
}else{ |
604
|
|
|
whole = numStr; |
605
|
|
|
decimal = null; |
606
|
|
|
} |
607
|
|
|
|
608
|
|
|
// if at least 4 digits |
609
|
|
|
if (whole.length > 3) { |
610
|
|
|
|
611
|
|
|
// extract 3 digits first |
612
|
|
|
var wholeRight3 = whole.substr(whole.length - 3, 3); |
613
|
|
|
whole = whole.substr(0, whole.length - 3); |
614
|
|
|
|
615
|
|
|
// add million / crore seperators |
616
|
|
|
if (whole.length < commas) { |
617
|
|
|
whole = whole + "," + wholeRight3; |
618
|
|
|
}else { |
619
|
|
|
var thou = ""; |
620
|
|
|
var rem = whole.substr(0, int(whole.length % commas)); |
621
|
|
|
var l = ((int(whole.length / commas)*commas) - commas) + (whole.length % commas); |
622
|
|
|
for (var c = 0;l >= 0;l -= commas, c++){ |
|
|
|
|
623
|
|
|
thou = whole.substr(l, commas) + (c === 0 ? "" : ",") + thou; |
624
|
|
|
} |
625
|
|
|
whole = (rem == "" ? "" : rem + ",") + thou + "," + wholeRight3; |
626
|
|
|
} |
627
|
|
|
} |
628
|
|
|
|
629
|
|
|
// return with or without dot |
630
|
|
|
var result = whole; |
631
|
|
|
if (hasDot) { |
632
|
|
|
if (decimals > 0) { |
633
|
|
|
// 4.200 |
634
|
|
|
result = whole + "." + decimal.substr(0, decimals).padRight("0", decimals); |
635
|
|
|
}else if (decimals === 0) { |
|
|
|
|
636
|
|
|
// 4 |
637
|
|
|
//result = whole; |
638
|
|
|
}else if (decimals === -1) { |
639
|
|
|
// 4.2 |
640
|
|
|
result = whole + "." + decimal; |
641
|
|
|
} |
642
|
|
|
|
643
|
|
|
}else if (alwaysShowDecimal && decimals > 0) { |
644
|
|
|
|
645
|
|
|
// 4.0000 |
646
|
|
|
result = whole + "." + decimals.repeat("0"); |
647
|
|
|
}else { |
|
|
|
|
648
|
|
|
|
649
|
|
|
// 4 |
650
|
|
|
//result = whole; |
651
|
|
|
} |
652
|
|
|
return (neg ? "-" + result : result); |
653
|
|
|
}, |
654
|
|
|
|
655
|
|
|
ensureNotNaN: function(instead = 0){ |
656
|
|
|
var val = this; |
657
|
|
|
if (val != val) { /// fast isNaN check |
658
|
|
|
return instead; |
659
|
|
|
} |
660
|
|
|
return val; |
661
|
|
|
}, |
662
|
|
|
|
663
|
|
|
scale: function(inputMin, inputMax, outputMin, outputMax, outputLimit = true, outputFlip = false){ |
664
|
|
|
var input = this; |
665
|
|
|
|
666
|
|
|
// ensure input within limits |
667
|
|
|
if (input < inputMin) { |
668
|
|
|
input = inputMin; |
669
|
|
|
} |
670
|
|
|
if (input > inputMax) { |
671
|
|
|
input = inputMax; |
672
|
|
|
} |
673
|
|
|
|
674
|
|
|
// convert input to % |
675
|
|
|
var percent = ((1*(input - inputMin)) / (inputMax - inputMin)); |
676
|
|
|
|
677
|
|
|
// convert % to output |
678
|
|
|
var output = (percent*(outputMax - outputMin)) + outputMin; |
679
|
|
|
|
680
|
|
|
// ensure output within limits |
681
|
|
|
if (outputLimit){ |
682
|
|
|
if (output < outputMin) { |
683
|
|
|
output = outputMin; |
684
|
|
|
} |
685
|
|
|
if (output > outputMax) { |
686
|
|
|
output = outputMax; |
687
|
|
|
} |
688
|
|
|
} |
689
|
|
|
|
690
|
|
|
// flip output |
691
|
|
|
if (outputFlip) { |
692
|
|
|
output = ((outputMax - outputMin) - (output - outputMin)) + outputMin; |
693
|
|
|
} |
694
|
|
|
|
695
|
|
|
// return scaled, limit-checked output |
696
|
|
|
return output; |
697
|
|
|
}, |
698
|
|
|
smartScale: function(inputMin, inputMax, outputMin, outputMax){ |
699
|
|
|
var input = this; |
700
|
|
|
if (inputMin > inputMax) { |
701
|
|
|
if (outputMin > outputMax) { |
702
|
|
|
return input.flipWithin(inputMin, inputMax).scale(inputMax, inputMin, outputMax, outputMin, true, true); |
703
|
|
|
} |
704
|
|
|
return input.flipWithin(inputMin, inputMax).scale(inputMax, inputMin, outputMin, outputMax); |
705
|
|
|
} |
706
|
|
|
if (outputMin > outputMax) { |
707
|
|
|
return input.scale(inputMin, inputMax, outputMax, outputMin, true, true); |
708
|
|
|
} |
709
|
|
|
return input.scale(inputMin, inputMax, outputMin, outputMax); |
710
|
|
|
}, |
711
|
|
|
|
712
|
|
|
flipWithin: function(min, max){ |
713
|
|
|
var input = this; |
714
|
|
|
if (max < min) { |
715
|
|
|
return ((min - max) - (input - max)) + min; |
716
|
|
|
} |
717
|
|
|
return ((max - min) - (input - min)) + min; |
718
|
|
|
}, |
719
|
|
|
|
720
|
|
|
limitToDigits: function(digits){ |
721
|
|
|
var input = this; |
722
|
|
|
return parseFloat(input.toString().substr(0, digits)); |
723
|
|
|
}, |
724
|
|
|
limit: function(min, max){ |
725
|
|
|
var input = this; |
726
|
|
|
|
727
|
|
|
// ensure ok |
728
|
|
|
if (input != input) { /// fast isNaN check |
729
|
|
|
return min; |
730
|
|
|
} |
731
|
|
|
|
732
|
|
|
// flip limits if in reverse order |
733
|
|
|
if (min > max) { |
734
|
|
|
var temp = max; |
735
|
|
|
max = min; |
736
|
|
|
min = temp; |
737
|
|
|
} |
738
|
|
|
|
739
|
|
|
// ensure within limits |
740
|
|
|
if (input < min) { |
741
|
|
|
return min; |
742
|
|
|
}else if (input > max) { |
743
|
|
|
return max; |
744
|
|
|
} |
745
|
|
|
return input; |
746
|
|
|
}, |
747
|
|
|
limitToArray: function(array, extraMax = 0, extraMin = 0){ |
748
|
|
|
var pointer = this; |
749
|
|
|
if (pointer <= -extraMin) { |
750
|
|
|
return -extraMin; |
751
|
|
|
} |
752
|
|
|
var last = (array.length + extraMax) - 1; |
753
|
|
|
if (last === -1) { |
754
|
|
|
return -extraMin; |
755
|
|
|
}else if (pointer > last) { |
756
|
|
|
return last; |
757
|
|
|
} |
758
|
|
|
return pointer; |
759
|
|
|
}, |
760
|
|
|
|
761
|
|
|
wrap: function(min, max){ |
762
|
|
|
var input = this; |
763
|
|
|
|
764
|
|
|
// flip limits if in reverse order |
765
|
|
|
if (min > max) { |
766
|
|
|
var temp = max; |
767
|
|
|
max = min; |
768
|
|
|
min = temp; |
769
|
|
|
} |
770
|
|
|
|
771
|
|
|
// ensure wrapped to limits |
772
|
|
|
var diff = (max - min) + 1; |
773
|
|
|
while (input < min) { |
774
|
|
|
input += diff; |
775
|
|
|
} |
776
|
|
|
while (input > max) { |
777
|
|
|
input -= diff; |
778
|
|
|
} |
779
|
|
|
return input; |
780
|
|
|
}, |
781
|
|
|
wrapToMax: function(max){ |
782
|
|
|
var value = this; |
783
|
|
|
var diff = max + 1; |
784
|
|
|
while (value < 0) { |
785
|
|
|
value += diff; |
786
|
|
|
} |
787
|
|
|
return value % diff; |
788
|
|
|
}, |
789
|
|
|
|
790
|
|
|
/** Identical to modulo operator, except negative values are also supported, and brought into positive range. |
791
|
|
|
Value will never reach limit, just like the modulo operator. |
792
|
|
|
Simpler than `wrap` which takes `min` and `max`. */ |
793
|
|
|
modulo: function(limit){ |
794
|
|
|
var input = this; |
795
|
|
|
|
796
|
|
|
// ensure wrapped to limits |
797
|
|
|
while (input < 0) { |
798
|
|
|
input += limit; |
799
|
|
|
} |
800
|
|
|
while (input >= limit) { |
801
|
|
|
input -= limit; |
802
|
|
|
} |
803
|
|
|
return input; |
804
|
|
|
}, |
805
|
|
|
|
806
|
|
|
roundToDigits: function(decimals = 4){ |
807
|
|
|
var input = this; |
808
|
|
|
|
809
|
|
|
if (decimals <= 0) { |
810
|
|
|
return Math.round(input); |
811
|
|
|
} |
812
|
|
|
|
813
|
|
|
// Returns a number rounded to specified number of decimals |
814
|
|
|
var multiplier = Math.pow(10, decimals); |
815
|
|
|
return Math.round(input*multiplier)/multiplier; |
816
|
|
|
}, |
817
|
|
|
roundTo: function(decimals){ |
818
|
|
|
var input = this; |
819
|
|
|
|
820
|
|
|
// Returns a number rounded to specified number of decimals |
821
|
|
|
// Add zeros to always return those many decimals |
822
|
|
|
var num = input.roundToDigits(decimals).toString(); |
823
|
|
|
if (decimals <= 0) { |
824
|
|
|
return num; |
825
|
|
|
} |
826
|
|
|
var add0 = 0; |
827
|
|
|
if (num.lastIndexOf(".") === -1){ |
828
|
|
|
num = num+"."; |
829
|
|
|
add0 = decimals; |
830
|
|
|
}else{ |
831
|
|
|
add0 = decimals - ((num.length - num.lastIndexOf(".")) - 1); |
832
|
|
|
} |
833
|
|
|
while(add0 > 0){ |
834
|
|
|
num = num+"0"; |
835
|
|
|
add0 --; |
836
|
|
|
} |
837
|
|
|
return num; |
838
|
|
|
}, |
839
|
|
|
|
840
|
|
|
|
841
|
|
|
|
842
|
|
|
// HEX |
843
|
|
|
toHex: function(digits = 6, withHash = true){ |
844
|
|
|
var num = this; |
845
|
|
|
var zeros = ("0000000000000000000000000000000000").substr(0, digits - 1); |
846
|
|
|
return ((withHash ? "#" : "") + (zeros + num.toString(16).toUpperCase()).substr( -digits)); |
847
|
|
|
}, |
848
|
|
|
|
849
|
|
|
incrementWithin: function(min, max){ |
850
|
|
|
var num = this; |
851
|
|
|
num++; |
852
|
|
|
if (num > max) { |
853
|
|
|
return min; |
854
|
|
|
} |
855
|
|
|
return num; |
856
|
|
|
}, |
857
|
|
|
decrementWithin: function(min, max){ |
858
|
|
|
var num = this; |
859
|
|
|
num--; |
860
|
|
|
if (num < min) { |
861
|
|
|
return max; |
862
|
|
|
} |
863
|
|
|
return num; |
864
|
|
|
}, |
865
|
|
|
|
866
|
|
|
|
867
|
|
|
decimalToBinary: function(digits = 8, alt = false){ |
868
|
|
|
if (alt){ |
869
|
|
|
var byte = this; |
870
|
|
|
var bin = ''; |
871
|
|
|
for (var i = 0;i<digits;i++){ |
872
|
|
|
bin += String((byte & (0x80 >> i)) >> (7 - i)); |
873
|
|
|
} |
874
|
|
|
return bin; |
875
|
|
|
} |
876
|
|
|
var num = this; |
877
|
|
|
var zeros = UB.decZeros.substr(0, digits - 1); |
878
|
|
|
return (zeros + num.toString(2)).substr( -digits); |
879
|
|
|
}, |
880
|
|
|
|
881
|
|
|
|
882
|
|
|
|
883
|
|
|
// MISC MATH |
884
|
|
|
pad: function(length, addToEnd = false, padChar = '0'){ |
885
|
|
|
var number = this; |
886
|
|
|
|
887
|
|
|
// num to text |
888
|
|
|
var result = String(number); |
889
|
|
|
|
890
|
|
|
// exit quickly if already reached target len |
891
|
|
|
if (result.length >= length) { |
892
|
|
|
return result; |
893
|
|
|
} |
894
|
|
|
|
895
|
|
|
|
896
|
|
|
// pad |
897
|
|
|
if (addToEnd) { |
898
|
|
|
while (result.length < length){ |
899
|
|
|
result = result + padChar; |
900
|
|
|
} |
901
|
|
|
}else { |
902
|
|
|
while (result.length < length){ |
903
|
|
|
result = padChar + result; |
904
|
|
|
} |
905
|
|
|
} |
906
|
|
|
|
907
|
|
|
|
908
|
|
|
return result; |
909
|
|
|
}, |
910
|
|
|
interpolate: function(min, max){ |
911
|
|
|
var progress = this; |
912
|
|
|
// progress = (0 to 1) |
913
|
|
|
return min + ((max - min) * progress); |
914
|
|
|
}, |
915
|
|
|
hypot: function(b){ |
916
|
|
|
var a = this; |
917
|
|
|
// sqrt(a^2 + b^2) without under/overflow. |
918
|
|
|
|
919
|
|
|
var r; |
920
|
|
|
var aAbs = (a > 0 ? a : -a); |
921
|
|
|
var bAbs = (b > 0 ? b : -b); |
922
|
|
|
if (aAbs > bAbs) { |
923
|
|
|
r = b/a; |
924
|
|
|
r = aAbs*Math.sqrt(1+r*r); |
925
|
|
|
} else if (b != 0) { |
926
|
|
|
r = a/b; |
927
|
|
|
r = bAbs*Math.sqrt(1+r*r); |
928
|
|
|
} else { |
929
|
|
|
r = 0.0; |
930
|
|
|
} |
931
|
|
|
return r; |
932
|
|
|
}, |
933
|
|
|
apow: function(value){ |
934
|
|
|
var pow = this; |
935
|
|
|
// input: 1,2,4,8,16,32,64 |
936
|
|
|
// output: 1,2,3,4,5,6,7 |
937
|
|
|
if (value == 1 || value === -1) return value; |
|
|
|
|
938
|
|
|
var count = 0; |
939
|
|
|
while (value != 0) { |
940
|
|
|
//remainder = value % pow; |
941
|
|
|
value = value / pow; |
942
|
|
|
count++; |
943
|
|
|
} |
944
|
|
|
return count; |
945
|
|
|
}, |
946
|
|
|
invert: function(){ |
947
|
|
|
var value = this; |
948
|
|
|
// input: 0.1 0.5 1 2 8 |
949
|
|
|
// output: 10 2 1 0.5 0.2 |
950
|
|
|
return 1 / value; |
951
|
|
|
}, |
952
|
|
|
powAbs: function(exponent){ |
953
|
|
|
var x = this; |
954
|
|
|
// This function always returns a positive value that conforms to the expected Exponent curve. |
955
|
|
|
// Math.pow: If x is negative, and exponent is not an integer, returns NaN. |
956
|
|
|
if( x >= 0 ) { |
957
|
|
|
return Math.pow( x, exponent ); |
958
|
|
|
} |
959
|
|
|
return Math.pow(-x, 1/exponent); |
960
|
|
|
}, |
961
|
|
|
|
962
|
|
|
// count digits in number |
963
|
|
|
getWhole: function(){ |
964
|
|
|
var val = this; |
965
|
|
|
|
966
|
|
|
// -10.235 has 2 whole digits |
967
|
|
|
return int(val); |
968
|
|
|
}, |
969
|
|
|
setWhole: function(newval){ |
970
|
|
|
var val = this; |
971
|
|
|
return newval + GetFractional(val); |
972
|
|
|
}, |
973
|
|
|
getFractional: function(){ |
974
|
|
|
var val = this; |
975
|
|
|
|
976
|
|
|
// -10.235 has 3 fractional digits |
977
|
|
|
var s = (val < 0 ? -val : val).toString(); |
978
|
|
|
var i = s.indexOf("."); |
979
|
|
|
return (i === -1) ? int(val) : int(s.substr(i + 1)); |
980
|
|
|
}, |
981
|
|
|
setFractional: function(fraction){ |
982
|
|
|
var val = this; |
983
|
|
|
return Number((parseInt(val).toString()) + "." + fraction.toString()); |
984
|
|
|
}, |
985
|
|
|
|
986
|
|
|
|
987
|
|
|
|
988
|
|
|
// SLOT INDEX |
989
|
|
|
minIndex: function(index2){ |
990
|
|
|
var index1 = this; |
991
|
|
|
if (index1 <= -1) { |
992
|
|
|
return index2; |
993
|
|
|
} |
994
|
|
|
if (index2 <= -1) { |
995
|
|
|
return index1; |
996
|
|
|
} |
997
|
|
|
if (index1 < index2) { |
998
|
|
|
return index1; |
999
|
|
|
} |
1000
|
|
|
return index2; |
1001
|
|
|
}, |
1002
|
|
|
maxIndex: function(index2){ |
1003
|
|
|
var index1 = this; |
1004
|
|
|
if (index1 <= -1) { |
1005
|
|
|
return index2; |
1006
|
|
|
} |
1007
|
|
|
if (index2 <= -1) { |
1008
|
|
|
return index1; |
1009
|
|
|
} |
1010
|
|
|
if (index1 > index2) { |
1011
|
|
|
return index1; |
1012
|
|
|
} |
1013
|
|
|
return index2; |
1014
|
|
|
}, |
1015
|
|
|
|
1016
|
|
|
|
1017
|
|
|
|
1018
|
|
|
none:null |
1019
|
|
|
}; |
1020
|
|
|
|
1021
|
|
|
// register funcs |
1022
|
|
|
UB.registerFuncs(Number.prototype, numberFuncs); |
1023
|
|
|
|
1024
|
|
|
|